﻿using GBT.Entity.GBT_Manage;
using GBT.Util;
using EFCore.Sharding;
using LinqKit;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using System.Linq.Expressions;
using System;
using GBT.Entity.Base_Manage;
using GBT.Entity.GBT_Base_Manage;
using GBT.Entity;
using System.Data;
using AutoMapper.QueryableExtensions;
using System.Runtime.InteropServices.ComTypes;
using Microsoft.Extensions.ObjectPool;
using System.Security.Cryptography;

namespace GBT.Business.GBT_Manage
{
    public class GBT_ServiceRequestBusiness : BaseBusiness<GBT_ServiceRequest>, IGBT_ServiceRequestBusiness, ITransientDependency
    {
        public GBT_ServiceRequestBusiness(IDbAccessor db)
            : base(db)
        {
        }

        DDApi.DDApi ddApi = new DDApi.DDApi();
        #region 外部接口

        public async Task<PageResult<GBT_ServiceRequestDTO>> GetDataListAsync(PageInput<GBT_ServiceRequestConditionDTO> input)
        {
            var q = GetIQueryable();
            var where = LinqHelper.True<GBT_ServiceRequestDTO>();
            var search = input.Search;

            Expression<Func<GBT_ServiceRequest, GBT_Base_Account, Base_User, Base_User, GBT_ServiceRequestDTO>> select = (sr, ba, bu, cbu) => new GBT_ServiceRequestDTO
            {
                RequestDepartmentId = "",
                DeliveryDepartmentId = "",
                AccountName = ba.Name,
                ApprovalName = bu.UserName,
                ApprovalOpinion = "",
                CreatorName = cbu.UserName,
            };
            select = select.BuildExtendSelectExpre();

            var list = from sr in q.AsExpandable()
                       join ba in Db.GetIQueryable<GBT_Base_Account>() on sr.AccountId equals ba.Id
                       join bu in Db.GetIQueryable<Base_User>() on sr.Approver equals bu.Id into bu_temp
                       from bu in bu_temp.DefaultIfEmpty()
                       join cbu in Db.GetIQueryable<Base_User>() on sr.CreatorId equals cbu.Id into cbu_temp
                       from cbu in cbu_temp.DefaultIfEmpty()
                       select @select.Invoke(sr, ba, bu, cbu);

            //筛选
            if (!search.Condition.IsNullOrEmpty() && !search.Keyword.IsNullOrEmpty())
            {
                var newWhere = DynamicExpressionParser.ParseLambda<GBT_ServiceRequestDTO, bool>(
                    ParsingConfig.Default, false, $@"{search.Condition}.Contains(@0)", search.Keyword);
                where = where.And(newWhere);
            }
            //PT --- C：创建人，创建人查看列表；A：我的已审，我审核过的单据列表
            where = where.AndIf(!search.UserId.IsNullOrEmpty() && search.PT == "C", t => t.CreatorId.Equals(search.UserId));
            where = where.AndIf(!search.PT.IsNullOrEmpty() && search.PT != "C", t => !t.State.Equals(4));
            where = where.AndIf(!search.Approver.IsNullOrEmpty(), t => t.Approver.Equals(search.Approver));
            var approvalList = await GetApprovalToUser(search.UserId);
            where = where.AndIf(search.PT.Equals("A"), t => approvalList.Contains(t.Id));
            var listNew = await list.Where(where).OrderBy(t => t.State).ThenByDescending(t => t.CreateTime).GetPageResultAsync(input);
            
            await SetProperty(listNew.Data);

            return listNew;
        }

        public async Task<GBT_ServiceRequest> GetTheDataAsync(string id)
        {
            Expression<Func<GBT_ServiceRequest, GBT_Base_Account, GBT_ServiceRequestDTO>> select = (sr, ba) => new GBT_ServiceRequestDTO
            {
                RequestDepartmentId = "",
                DeliveryDepartmentId = "",
                AccountName = ba.Name
            };
            select = select.BuildExtendSelectExpre();

            var list = from sr in GetIQueryable().AsExpandable()
                       join ba in Db.GetIQueryable<GBT_Base_Account>() on sr.AccountId equals ba.Id
                       where sr.Id == id
                       select @select.Invoke(sr, ba);
            var listNew = await list.ToListAsync();
            //可以考虑按ID设置属性 节省 in 条件的性能损耗
            await SetProperty(listNew);
            var serviceRequest = listNew.FirstOrDefault();
            return serviceRequest;
        }

        public async Task<List<GBT_ServiceRequestUserDTO>> GetServiceRequestUserListAsync(List<string> departmentIds, string requestId, string userId)
        {
            var requestUserList = from bu in Db.GetIQueryable<Base_User>()
                                  join sru in Db.GetIQueryable<GBT_ServiceRequestUser>().Where(t => t.CreatorId == userId && t.ServiceRequestId == requestId) on bu.Id equals sru.UserId into RequestUser
                                  from sru in RequestUser.DefaultIfEmpty()
                                  where departmentIds.Contains(bu.DepartmentId) && bu.Id != "Admin"
                                  select new GBT_ServiceRequestUserDTO
                                  {
                                      Id = sru.Id,
                                      ServiceRequestId = sru.ServiceRequestId,
                                      UserId = bu.Id,
                                      Score = sru.Score,
                                      Amount = sru.Amount,
                                      UserName = bu.UserName,
                                      CreatorId = sru.CreatorId,
                                      CreateTime = sru.CreateTime,
                                  };
            var reuqestUsers = await requestUserList.ToListAsync();

            return reuqestUsers;
        }

        public async Task<List<GBT_ServiceDeliveryUserDTO>> GetServiceDeliveryUserListAsync(List<string> departmentIds, string requestId, string userId)
        {
            var deliveryUserList = from bu in Db.GetIQueryable<Base_User>()
                                   join sdu in Db.GetIQueryable<GBT_ServiceDeliveryUser>().Where(t => t.CreatorId == userId && t.ServiceRequestId == requestId) on bu.Id equals sdu.UserId into DeliveryUser
                                   from sdu in DeliveryUser.DefaultIfEmpty()
                                   join d in Db.GetIQueryable<Base_Department>() on bu.DepartmentId equals d.Id
                                   where departmentIds.Contains(bu.DepartmentId) && bu.Id != "Admin"
                                   select new GBT_ServiceDeliveryUserDTO
                                   {
                                       Id = sdu.Id,
                                       ServiceRequestId = sdu.ServiceRequestId,
                                       DepartmentName = d.Name,
                                       UserId = bu.Id,
                                       Amount = sdu.Amount,
                                       Principal = sdu.Principal,
                                       UserName = bu.UserName,
                                       CreatorId = sdu.CreatorId,
                                       CreateTime = sdu.CreateTime,
                                   };
            return await deliveryUserList.ToListAsync();
        }

        public async Task<PageResult<GBT_ServiceItemsDTO>> GetServiceItemsListAsync(PageInput<GBT_Base_ServiceItemConditionDTO> input)
        {
            var where = LinqHelper.True<GBT_ServiceItemsDTO>();
            var search = input.Search;
            var departmentId = search.DepartmentId;
            Expression<Func<GBT_Base_ServiceItems, Base_Department, GBT_Base_Account, GBT_ServiceItems, GBT_ServiceItemsDTO>> select = (bsi, d, a, si) => new GBT_ServiceItemsDTO
            {
                Id = si.Id,
                DepartmentId = bsi.DepartmentId,
                Number = bsi.Number,
                Name = bsi.Name,
                Content = bsi.Content,
                Price = bsi.Price,
                AccountName = a.Name,
                ServiceItemId = bsi.Id,
                ServiceRequestId = si.ServiceRequestId,
            };
            select = select.BuildExtendSelectExpre();

            var serviceItemList = from bsi in Db.GetIQueryable<GBT_Base_ServiceItems>().AsExpandable()
                                  join d in Db.GetIQueryable<Base_Department>() on bsi.DepartmentId equals d.Id into d_temp
                                  from d in d_temp.DefaultIfEmpty()
                                  join a in Db.GetIQueryable<GBT_Base_Account>() on bsi.AccountId equals a.Id into a_temp
                                  from a in a_temp.DefaultIfEmpty()
                                  join si in Db.GetIQueryable<GBT_ServiceItems>().Where(t => t.CreatorId == search.UserId && t.ServiceRequestId == search.RequestId) on bsi.Id equals si.ServiceItemId into si_temp
                                  from si in si_temp.DefaultIfEmpty()
                                  where departmentId.Contains(bsi.DepartmentId)
                                  select @select.Invoke(bsi, d, a, si);

            //筛选
            if (!search.Condition.IsNullOrEmpty() && !search.Keyword.IsNullOrEmpty())
            {
                var newWhere = DynamicExpressionParser.ParseLambda<GBT_ServiceItemsDTO, bool>(
                    ParsingConfig.Default, false, $@"{search.Condition}.Contains(@0)", search.Keyword);
                where = where.And(newWhere);
            }

            return await serviceItemList.Where(where).GetPageResultAsync(input);
        }

        public async Task<List<GBT_ApprovalDTO>> GetApprovalListAsync(List<string> deptIds, string requestId, int State)
        {
            List<GBT_ApprovalDTO> _ApprovalDTOs = new List<GBT_ApprovalDTO>();
            List<string> requestIds = new List<string>();
            requestIds.Add(requestId);
            switch (State)
            {
                case 0:
                    //下一步 状态为1 的审批人列表
                    _ApprovalDTOs = await GetDepartmentHeadAsync(deptIds);
                    break;
                case 1:
                    //下一步 状态为2 的审批人列表
                    var deliveryUserList = await GetServiceDeliveryUser(requestIds);
                    _ApprovalDTOs = deliveryUserList.Select(t => new GBT_ApprovalDTO
                    {
                        DepartmentId = t.DepartmentId,
                        UserId = t.UserId,
                        DepartmentName = t.DepartmentName,
                        UserName = t.UserName,
                    }).ToList();
                    break;
                case 2:
                    //下一步 状态为3 的审批人列表
                    var requestUserList = await GetServiceRequestUser(requestIds);
                    _ApprovalDTOs = requestUserList.Select(t => new GBT_ApprovalDTO
                    {
                        DepartmentId = t.DepartmentId,
                        UserId = t.UserId,
                        DepartmentName = t.DepartmentName,
                        UserName = t.UserName,
                    }).ToList();
                    break;
            }
            return _ApprovalDTOs;
        }

        public async Task<List<GBT_ApprovalDTO>> GetApprovalHistoryAsync(string requestId)
        {
            var approvalList = from ga in Db.GetIQueryable<GBT_Approval>()
                               join u in Db.GetIQueryable<Base_User>() on ga.UserId equals u.Id
                               where ga.ServiceRequestId == requestId
                               select new GBT_ApprovalDTO
                               {
                                   Id = ga.Id,
                                   DepartmentId = ga.DepartmentId,
                                   UserId = ga.UserId,
                                   UserName = u.UserName,
                                   State = ga.State,
                                   StateName = ga.State == 0 ? "发起" : ga.State == 1 ? "审批" : ga.State == 2 ? "完工确认" : ga.State == 3 ? "评价" : "完结",
                                   Remark = ga.Remark,
                                   CreatorId = ga.CreatorId,
                                   CreateTime = ga.CreateTime,
                               };
            return await approvalList.ToListAsync();
        }

        public async Task EvaluateAsync(GBT_ServiceRequestDTO data, string userId)
        {
            var requestUsers = data.RequestUsers.Where(t => t.UserId == userId).FirstOrDefault();
            requestUsers.Score = data.Source;
            requestUsers.Describe = data.ApprovalOpinion;
            await Db.UpdateAsync(requestUsers);
            await ApprovalAsync(data, userId);
        }

        public async Task AddDataAsync(GBT_ServiceRequestDTO data)
        {
            await InsertAsync(data);
        }

        public async Task UpdateDataAsync(GBT_ServiceRequestDTO data)
        {
            await UpdateAsync(data);
        }

        [Transactional]
        public async Task SaveDataAsync(GBT_ServiceRequestDTO data, string userId)
        {
            //项目明细不为空，则计算总金额
            if (!data.ServiceItems.IsNullOrEmpty())
            {
                decimal amount = 0;
                data.ServiceItems.ForEach(t =>
                {
                    if (t.Quantity.IsNullOrEmpty() || t.Quantity == 0)
                    {
                        t.Quantity = 1;
                    }
                    amount += t.Quantity * t.Price;
                });
                data.Amount = amount;
                //请求服务人员分摊支出金额
                if (!data.RequestUsers.IsNullOrEmpty())
                {
                    var count = data.RequestUsers.Count;
                    List<GBT_ServiceRequestUserDTO> _ServiceRequestUserDTOs = new List<GBT_ServiceRequestUserDTO>();
                    decimal? currentTotalAmount = 0;
                    int currentIndex = 0;
                    data.RequestUsers.ForEach(t =>
                    {
                        if (t.Amount.IsNullOrEmpty() || t.Amount == 0)
                        {
                            t.Amount = Math.Round(amount / count, 2);
                        }
                        else if (currentTotalAmount <= data.Amount && currentIndex == data.RequestUsers.Count - 1)
                        {
                            t.Amount = data.Amount - currentTotalAmount;
                        }
                        _ServiceRequestUserDTOs.Add(t);
                        currentTotalAmount += t.Amount.IsNullOrEmpty() ? 0 : t.Amount;
                        //超出最大金额时调整
                        if (currentTotalAmount > data.Amount)
                        {
                            t.Amount = data.Amount - currentTotalAmount + t.Amount;
                        }
                        currentIndex++;
                    });
                    data.RequestUsers = _ServiceRequestUserDTOs;
                }
                //提供服务人员分摊收入金额
                if (!data.DeliveryUsers.IsNullOrEmpty())
                {
                    var count = data.DeliveryUsers.Count;
                    List<GBT_ServiceDeliveryUserDTO> _ServiceDeliveryUserDTOs = new List<GBT_ServiceDeliveryUserDTO>();
                    decimal? currentTotalAmount = 0;
                    int currentIndex = 0;
                    data.DeliveryUsers.ForEach(t =>
                    {
                        if (t.Amount.IsNullOrEmpty() || t.Amount == 0)
                        {
                            t.Amount = Math.Round(amount / count, 2);
                        }
                        else if (currentTotalAmount <= data.Amount && currentIndex == data.DeliveryUsers.Count - 1)
                        {
                            t.Amount = data.Amount - currentTotalAmount;
                        }
                        _ServiceDeliveryUserDTOs.Add(t);
                        currentTotalAmount += t.Amount.IsNullOrEmpty() ? 0 : t.Amount;
                        //超出最大金额时调整
                        if (currentTotalAmount > data.Amount)
                        {
                            t.Amount = data.Amount - currentTotalAmount + t.Amount;
                        }
                        currentIndex++;
                    });
                    data.DeliveryUsers = _ServiceDeliveryUserDTOs;
                }
            }

            if (data.Id.IsNullOrEmpty())
            {
                data.Id = IdHelper.GetId();
                data.CreatorId = userId;
                data.CreateTime = DateTime.Now;
                await AddDataAsync(data);
            }
            else
            {
                await UpdateDataAsync(data);
            }

            #region 已有数据清理
            await ClearServiceRequestUser(data);
            await ClearServiceDeliveryUser(data);
            await ClearServiceItems(data);
            #endregion

            await AddOrModifyServiceReuqestUser(data, userId);
            await AddOrModifyServiceDeliveryUser(data, userId);
            await AddOrModifyServiceItems(data, userId);
        }

        [Transactional]
        public async Task ApprovalAsync(GBT_ServiceRequestDTO data, string userId)
        {
            //写入审批记录
            await ClearApproval(data, userId);
            bool isSuccess = await AddApprovalAsync(data, userId);

            if (isSuccess)
            {
                //跳到下一步审批 变更状态
                switch (data.State)
                {
                    case 0:
                        //发起
                        data.State = 1;
                        break;
                    case 1:
                        //经理审批
                        data.State = 2;
                        break;
                    case 2:
                        //完工确认
                        data.State = 3;
                        break;
                    case 3:
                        //评价
                        data.State = 4;
                        break;
                }
                await Db.UpdateAsync(data);

                //审批成功则发送通知消息
                ddApi.SendMessage(data.Approver, "单据：" + data.Id + " 需要你处理，请登录阿米巴“首页->审批”进行处理。");
            }
        }

        [Transactional]
        public async Task DeleteDataAsync(List<string> ids)
        {
            await Db.DeleteAsync<GBT_ServiceRequestUser>(t => ids.Contains(t.ServiceRequestId));
            await Db.DeleteAsync<GBT_ServiceDeliveryUser>(t => ids.Contains(t.ServiceRequestId));
            await Db.DeleteAsync<GBT_ServiceItems>(t => ids.Contains(t.ServiceRequestId));
            await DeleteAsync(ids);
        }

        #endregion

        #region 私有成员
        /// <summary>
        /// 获取服务请求部门
        /// </summary>
        /// <param name="serviceRequestIds"></param>
        /// <returns></returns>
        private async Task<List<GBT_DepartmentIdsDTO>> GetServiceRequestDepartmentIds(List<string> serviceRequestIds)
        {
            var deptInfo = await (from d in Db.GetIQueryable<Base_Department>()
                                  select new Base_Department
                                  {
                                      Id = d.Id,
                                      Name = d.Name,
                                  }).ToListAsync();

            var departmentIds = await (from sru in Db.GetIQueryable<GBT_ServiceRequest>()
                                       where serviceRequestIds.Contains(sru.Id)
                                       select new GBT_DepartmentIdsDTO
                                       {
                                           resquestId = sru.Id,
                                           departmentIds = sru.RequestDepartmentId
                                       }).ToListAsync();

            departmentIds.ForEach(t =>
            {
                var dept = t.departmentIds.ToList<string>();
                List<string> deptName = new List<string>();
                dept.ForEach(str =>
                {
                    deptName.AddRange(deptInfo.Where(dept => dept.Id == str).Select(dept => dept.Name).ToList());
                });
                t.departmentNames = deptName.ToString<string>();
            });
            return departmentIds;
        }

        /// <summary>
        /// 获取提供服务部门
        /// </summary>
        /// <param name="serviceRequestIds"></param>
        /// <returns></returns>
        private async Task<List<GBT_DepartmentIdsDTO>> GetServiceDeliveryDepartmentIds(List<string> serviceRequestIds)
        {
            var deptInfo = await (from d in Db.GetIQueryable<Base_Department>()
                                  select new Base_Department
                                  {
                                      Id = d.Id,
                                      Name = d.Name,
                                  }).ToListAsync();

            var departmentIds = await (from sru in Db.GetIQueryable<GBT_ServiceRequest>()
                                       where serviceRequestIds.Contains(sru.Id)
                                       select new GBT_DepartmentIdsDTO
                                       {
                                           resquestId = sru.Id,
                                           departmentIds = sru.DeliveryDepartmentId
                                       }).ToListAsync();

            departmentIds.ForEach(t =>
            {
                var dept = t.departmentIds.ToList<string>();
                List<string> deptName = new List<string>();
                dept.ForEach(str =>
                {
                    deptName.AddRange(deptInfo.Where(dept => dept.Id == str).Select(dept => dept.Name).ToList());
                });
                t.departmentNames = deptName.ToString<string>();
            });
            return departmentIds;
        }

        /// <summary>
        /// 获取服务请求人员
        /// </summary>
        /// <param name="serviceRequestIds"></param>
        /// <returns></returns>
        private async Task<List<GBT_ServiceRequestUserDTO>> GetServiceRequestUser(List<string> serviceRequestIds)
        {
            var requestUserList = await (from sru in Db.GetIQueryable<GBT_ServiceRequestUser>()
                                         join bu in Db.GetIQueryable<Base_User>() on sru.UserId equals bu.Id
                                         where serviceRequestIds.Contains(sru.ServiceRequestId)
                                         select new GBT_ServiceRequestUserDTO
                                         {
                                             Id = sru.Id,
                                             ServiceRequestId = sru.ServiceRequestId,
                                             UserId = sru.UserId,
                                             DepartmentId = bu.DepartmentId,
                                             Score = sru.Score,
                                             Describe = sru.Describe,
                                             Amount = sru.Amount,
                                             UserName = bu.UserName,
                                             CreatorId = sru.CreatorId,
                                             CreateTime = sru.CreateTime,
                                         }).ToListAsync();
            return requestUserList;
        }

        /// <summary>
        /// 获取提供服务人员
        /// </summary>
        /// <param name="serviceRequestIds"></param>
        /// <returns></returns>
        private async Task<List<GBT_ServiceDeliveryUserDTO>> GetServiceDeliveryUser(List<string> serviceRequestIds)
        {
            var deliveryUserList = await (from sdu in Db.GetIQueryable<GBT_ServiceDeliveryUser>()
                                          join bu in Db.GetIQueryable<Base_User>() on sdu.UserId equals bu.Id
                                          where serviceRequestIds.Contains(sdu.ServiceRequestId)
                                          select new GBT_ServiceDeliveryUserDTO
                                          {
                                              Id = sdu.Id,
                                              ServiceRequestId = sdu.ServiceRequestId,
                                              UserId = sdu.UserId,
                                              DepartmentId = bu.DepartmentId,
                                              Amount = sdu.Amount,
                                              Principal = sdu.Principal,
                                              UserName = bu.UserName,
                                              CreatorId = sdu.CreatorId,
                                              CreateTime = sdu.CreateTime,
                                          }).ToListAsync();
            return deliveryUserList;
        }

        /// <summary>
        /// 获取服务项目
        /// </summary>
        /// <param name="serviceRequestIds"></param>
        /// <returns></returns>
        private async Task<List<GBT_ServiceItemsDTO>> GetServiceItems(List<string> serviceRequestIds)
        {
            var serviceItemList = from si in Db.GetIQueryable<GBT_ServiceItems>()
                                  join bsi in Db.GetIQueryable<GBT_Base_ServiceItems>() on si.ServiceItemId equals bsi.Id into ServiceItems
                                  from bsi in ServiceItems.DefaultIfEmpty()
                                  where serviceRequestIds.Contains(si.ServiceRequestId)
                                  select new GBT_ServiceItemsDTO
                                  {
                                      Id = si.Id,
                                      ServiceRequestId = si.ServiceRequestId,
                                      ServiceItemId = bsi.Id,
                                      Number = bsi.Number,
                                      Name = bsi.Name,
                                      Content = bsi.Content,
                                      Price = bsi.Price,
                                      Quantity = si.Quantity,
                                      Remark = si.Remark,
                                      DepartmentId = bsi.DepartmentId,
                                      CreatorId = si.CreatorId,
                                      CreateTime = si.CreateTime,
                                  };

            return await serviceItemList.ToListAsync();
        }

        /// <summary>
        /// 获取部门主管列表
        /// </summary>
        /// <param name="deptId"></param>
        /// <returns></returns>
        private async Task<List<GBT_ApprovalDTO>> GetDepartmentHeadAsync(List<string> deptId)
        {
            var departmentHeadList = from dh in Db.GetIQueryable<Base_DepartmentHead>()
                                     join d in Db.GetIQueryable<Base_Department>() on dh.DepartmentId equals d.Id
                                     join u in Db.GetIQueryable<Base_User>() on dh.UserId equals u.Id
                                     where deptId.Contains(dh.DepartmentId)
                                     select new GBT_ApprovalDTO
                                     {
                                         DepartmentHeadId = dh.Id,
                                         DepartmentId = dh.DepartmentId,
                                         UserId = dh.UserId,
                                         DepartmentName = d.Name,
                                         UserName = u.UserName,
                                     };

            var deptHead = await departmentHeadList.ToListAsync();

            return deptHead.DistinctBy(t => t.UserId).ToList();
        }

        /// <summary>
        /// 获取包含登陆用户的 单据Id
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        private async Task<List<string>> GetApprovalToUser(string userId)
        {
            var approvalList = from ga in Db.GetIQueryable<GBT_Approval>()
                               join u in Db.GetIQueryable<Base_User>() on ga.UserId equals u.Id
                               where ga.UserId == userId 
                               select ga.ServiceRequestId;
            return await approvalList.ToListAsync();
        }

        /// <summary>
        /// 设置 请求服务人员列表，提供服务人员列表，服务项目列表，审批记录列表等属性
        /// </summary>
        /// <param name="serviceRequestList"></param>
        /// <returns></returns>
        private async Task SetProperty(List<GBT_ServiceRequestDTO> serviceRequestList)
        {
            List<string> serviceRequestIds = serviceRequestList.Select(x => x.Id).ToList();

            //服务请求部门
            var serviceRequestDepartments = await GetServiceRequestDepartmentIds(serviceRequestIds);

            //提供服务部门
            var serviceDeliveryDepartments = await GetServiceDeliveryDepartmentIds(serviceRequestIds);

            #region 请求服务人员
            var requestUserList = await GetServiceRequestUser(serviceRequestIds);
            #endregion

            #region 提供服务人员
            var deliveryUserList = await GetServiceDeliveryUser(serviceRequestIds);
            #endregion

            #region 服务项目
            var serviceItemList = await GetServiceItems(serviceRequestIds);
            #endregion

            #region 审批信息
            Expression<Func<GBT_Approval, Base_User, GBT_ApprovalDTO>> selectApproval = (a, bu) => new GBT_ApprovalDTO
            {
                UserName = bu.UserName,
            };
            selectApproval.BuildExtendSelectExpre();

            var approvalList = await (from a in Db.GetIQueryable<GBT_Approval>().AsExpandable()
                                      join bu in Db.GetIQueryable<Base_User>() on a.UserId equals bu.Id
                                      where serviceRequestIds.Contains(a.ServiceRequestId)
                                      select selectApproval.Invoke(a, bu)).ToListAsync();
            #endregion

            #region 返回结果
            serviceRequestList.ForEach(serviceRequest =>
            {
                serviceRequest.RequestDepartmentId = serviceRequestDepartments.Where(x => x.resquestId == serviceRequest.Id).Select(t => t.departmentIds).FirstOrDefault();
                serviceRequest.RequestDepartmentName = serviceRequestDepartments.Where(x => x.resquestId == serviceRequest.Id).Select(t => t.departmentNames).FirstOrDefault();
                serviceRequest.DeliveryDepartmentId = serviceDeliveryDepartments.Where(x => x.resquestId == serviceRequest.Id).Select(t => t.departmentIds).FirstOrDefault();
                serviceRequest.DeliveryDepartmentName = serviceDeliveryDepartments.Where(x => x.resquestId == serviceRequest.Id).Select(t => t.departmentNames).FirstOrDefault();
                var requestUsers = requestUserList.Where(x => x.ServiceRequestId == serviceRequest.Id);
                serviceRequest.RequestUsers = requestUsers.ToList();
                var deliveryUsers = deliveryUserList.Where(x => x.ServiceRequestId == serviceRequest.Id);
                serviceRequest.DeliveryUsers = deliveryUsers.ToList();
                var serviceItems = serviceItemList.Where(x => x.ServiceRequestId == serviceRequest.Id);
                serviceRequest.ServiceItems = serviceItems.ToList();
                var approvals = approvalList.Where(x => x.ServiceRequestId == serviceRequest.Id);
                serviceRequest.Approvals = approvals.ToList();
                var currentApproval = approvals.OrderByDescending(x => x.Id).FirstOrDefault();
                serviceRequest.CurrentApproval = currentApproval;
            });
            #endregion
        }

        /// <summary>
        /// 清理请求服务用户列表
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private async Task ClearServiceRequestUser(GBT_ServiceRequestDTO data)
        {
            List<string> requestIds = new List<string>();
            requestIds.Add(data.Id);
            //部门发生变化时，清理掉原先部门的信息
            List<GBT_ServiceRequestUserDTO> _ServiceRequestUserList = await GetServiceRequestUser(requestIds);
            var depts = data.RequestDepartmentId.ToList<string>();
            var _RequestUserList = _ServiceRequestUserList.Where(rt => rt.DepartmentId != null && !depts.Contains(rt.DepartmentId)).ToList();
            if (_RequestUserList.Count > 0)
            {
                List<string> ids = new List<string>();
                _RequestUserList.ForEach(t =>
                {
                    if (!t.Id.IsNullOrEmpty())
                        ids.Add(t.Id);
                });
                await Db.DeleteAsync<GBT_ServiceRequestUser>(t => ids.Contains(t.Id));
            }

            //客户端删除保存后的数据
            var _InputServiceRequestUserIds = data.RequestUsers.Where(t => t.ServiceRequestId != null).Select(t => t.Id).ToList();
            if (_InputServiceRequestUserIds.Count > 0)
            {
                //之前保存的信息里面存在且在本次提交的数据中不存在的信息 则删除
                var _DeleteServiceRequestUserIds = _ServiceRequestUserList.Where(rt => !_InputServiceRequestUserIds.Contains(rt.Id)).Select(t => t.Id).ToList();
                await Db.DeleteAsync<GBT_ServiceRequestUser>(t => _DeleteServiceRequestUserIds.Contains(t.Id));
            }
        }

        /// <summary>
        /// 清理提供服务用户列表
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private async Task ClearServiceDeliveryUser(GBT_ServiceRequestDTO data)
        {
            List<string> requestIds = new List<string>();
            requestIds.Add(data.Id);
            //部门发生变化时，清理掉原先部门的信息
            List<GBT_ServiceDeliveryUserDTO> _ServiceDeliveryUserList = await GetServiceDeliveryUser(requestIds);
            var depts = data.DeliveryDepartmentId.ToList<string>();
            var _DeliveryUserList = _ServiceDeliveryUserList.Where(dt => dt.DepartmentId != null && !depts.Contains(dt.DepartmentId)).ToList();
            if (_DeliveryUserList.Count > 0)
            {
                List<string> ids = new List<string>();
                _DeliveryUserList.ForEach(t =>
                {
                    if (!t.Id.IsNullOrEmpty())
                        ids.Add(t.Id);
                });
                await Db.DeleteAsync<GBT_ServiceDeliveryUser>(t => ids.Contains(t.Id));
            }

            //客户端删除保存后的数据
            var _InputServiceDeliveryUserIds = data.DeliveryUsers.Where(t => t.Id != null).Select(t => t.Id).ToList();
            if (_InputServiceDeliveryUserIds.Count > 0)
            {
                //之前保存的信息里面存在且在本次提交的数据中不存在的信息 则删除
                var _DeleteServiceDeliveryUserIds = _ServiceDeliveryUserList.Where(dt => !_InputServiceDeliveryUserIds.Contains(dt.Id)).Select(t => t.Id).ToList();
                await Db.DeleteAsync<GBT_ServiceDeliveryUser>(t => _DeleteServiceDeliveryUserIds.Contains(t.Id));
            }
        }

        /// <summary>
        /// 清理审批记录
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private async Task ClearApproval(GBT_ServiceRequestDTO data, string userId)
        {
            List<GBT_ApprovalDTO> _ApprovalDTOs = await GetApprovalHistoryAsync(data.Id);
            var _Approval = _ApprovalDTOs.Where(t => t.CreatorId == userId && t.ServiceRequestId == data.Id).FirstOrDefault();
            //创建人改变审批人且已存在审批人时，删除原先的审批人信息
            if (!_Approval.IsNullOrEmpty() && _Approval.UserId != data.Approver && _Approval.State == data.State)
            {
                await Db.DeleteAsync<GBT_ServiceDeliveryUser>(t => t.Id == _Approval.Id);
            }
        }

        /// <summary>
        /// 清理服务项目
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private async Task ClearServiceItems(GBT_ServiceRequestDTO data)
        {
            List<string> requestIds = new List<string>();
            requestIds.Add(data.Id);
            //部门发生变化时，清理掉原先部门的信息
            List<GBT_ServiceItemsDTO> _ServiceItemList = await GetServiceItems(requestIds);
            var depts = data.DeliveryDepartmentId.ToList<string>();
            var __ItemList = _ServiceItemList.Where(dt => dt.DepartmentId != null && !depts.Contains(dt.DepartmentId)).ToList();
            if (__ItemList.Count > 0)
            {
                List<string> ids = new List<string>();
                __ItemList.ForEach(t =>
                {
                    if (!t.Id.IsNullOrEmpty())
                        ids.Add(t.Id);
                });
                await Db.DeleteAsync<GBT_ServiceItems>(t => ids.Contains(t.Id));
            }

            //客户端删除保存后的数据
            var _InputServiceItemIds = data.ServiceItems.Where(t => t.Id != null).Select(t => t.Id).ToList();
            if (_InputServiceItemIds.Count > 0)
            {
                //之前保存的信息里面存在且在本次提交的数据中不存在的信息 则删除
                var _DeleteServiceDeliveryUserIds = _ServiceItemList.Where(dt => !_InputServiceItemIds.Contains(dt.Id)).Select(t => t.Id).ToList();
                await Db.DeleteAsync<GBT_ServiceItems>(t => _DeleteServiceDeliveryUserIds.Contains(t.Id));
            }
        }

        /// <summary>
        /// 添加或修改请求服务用户列表
        /// </summary>
        /// <param name="data"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        private async Task AddOrModifyServiceReuqestUser(GBT_ServiceRequestDTO data, string userId)
        {
            List<GBT_ServiceRequestUserDTO> _ServiceRequestUserDTOs_Insert = null;
            List<GBT_ServiceRequestUserDTO> _ServiceRequestUserDTOs_Update = null;

            if (!data.RequestUsers.IsNullOrEmpty())
            {
                var RequestDepartmentIds = data.RequestDepartmentId.ToList<string>();
                data.RequestUsers.ForEach(t =>
                {
                    if (t.Id.IsNullOrEmpty())
                    {
                        if (_ServiceRequestUserDTOs_Insert.IsNullOrEmpty())
                        {
                            _ServiceRequestUserDTOs_Insert = new List<GBT_ServiceRequestUserDTO>();
                        }
                        t.Id = IdHelper.GetId();
                        t.ServiceRequestId = data.Id;
                        t.CreatorId = userId;
                        t.CreateTime = DateTime.Now;
                        _ServiceRequestUserDTOs_Insert.Add(t);
                    }
                    else if (RequestDepartmentIds.Contains(t.DepartmentId))
                    {
                        if (_ServiceRequestUserDTOs_Update.IsNullOrEmpty())
                        {
                            _ServiceRequestUserDTOs_Update = new List<GBT_ServiceRequestUserDTO>();
                        }
                        _ServiceRequestUserDTOs_Update.Add(t);
                    }
                });
                if (!_ServiceRequestUserDTOs_Insert.IsNullOrEmpty())
                {
                    await Db.InsertAsync(_ServiceRequestUserDTOs_Insert);
                }
                if (!_ServiceRequestUserDTOs_Update.IsNullOrEmpty())
                {
                    await Db.UpdateAsync(_ServiceRequestUserDTOs_Update);
                }
            }
        }

        /// <summary>
        /// 添加或修改提供服务用户列表
        /// </summary>
        /// <param name="data"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        private async Task AddOrModifyServiceDeliveryUser(GBT_ServiceRequestDTO data, string userId)
        {
            List<GBT_ServiceDeliveryUserDTO> _ServiceDeliveryUserDTOs_Insert = null;
            List<GBT_ServiceDeliveryUserDTO> _ServiceDeliveryUserDTOs_Update = null;

            if (!data.DeliveryUsers.IsNullOrEmpty())
            {
                var DeliveryDepartmentIds = data.DeliveryDepartmentId.ToList<string>();
                data.DeliveryUsers.ForEach(t =>
                {
                    if (t.Id.IsNullOrEmpty())
                    {
                        if (_ServiceDeliveryUserDTOs_Insert.IsNullOrEmpty())
                        {
                            _ServiceDeliveryUserDTOs_Insert = new List<GBT_ServiceDeliveryUserDTO>();
                        }
                        t.Id = IdHelper.GetId();
                        t.ServiceRequestId = data.Id;
                        t.CreatorId = userId;
                        t.CreateTime = DateTime.Now;
                        _ServiceDeliveryUserDTOs_Insert.Add(t);
                    }
                    else if (DeliveryDepartmentIds.Contains(t.DepartmentId))
                    {
                        if (_ServiceDeliveryUserDTOs_Update.IsNullOrEmpty())
                        {
                            _ServiceDeliveryUserDTOs_Update = new List<GBT_ServiceDeliveryUserDTO>();
                        }
                        _ServiceDeliveryUserDTOs_Update.Add(t);
                    }
                });
                if (!_ServiceDeliveryUserDTOs_Insert.IsNullOrEmpty())
                {
                    await Db.InsertAsync(_ServiceDeliveryUserDTOs_Insert);
                }
                if (!_ServiceDeliveryUserDTOs_Update.IsNullOrEmpty())
                {
                    await Db.UpdateAsync(_ServiceDeliveryUserDTOs_Update);
                }
            }
        }

        /// <summary>
        /// 添加或修改服务项目
        /// </summary>
        /// <param name="data"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        private async Task AddOrModifyServiceItems(GBT_ServiceRequestDTO data, string userId)
        {
            List<GBT_ServiceItemsDTO> _ServiceItemsDTOs_Insert = null;
            List<GBT_ServiceItemsDTO> _ServiceItemsDTOs_Update = null;

            if (!data.ServiceItems.IsNullOrEmpty())
            {
                var DeliveryDepartmentIds = data.DeliveryDepartmentId.ToList<string>();
                data.ServiceItems.ForEach(t =>
                {
                    if (t.Id.IsNullOrEmpty())
                    {
                        if (_ServiceItemsDTOs_Insert.IsNullOrEmpty())
                        {
                            _ServiceItemsDTOs_Insert = new List<GBT_ServiceItemsDTO>();
                        }
                        t.Id = IdHelper.GetId();
                        t.ServiceRequestId = data.Id;
                        t.CreatorId = userId;
                        t.CreateTime = DateTime.Now;
                        _ServiceItemsDTOs_Insert.Add(t);
                    }
                    else if (DeliveryDepartmentIds.Contains(t.DepartmentId))
                    {
                        if (_ServiceItemsDTOs_Update.IsNullOrEmpty())
                        {
                            _ServiceItemsDTOs_Update = new List<GBT_ServiceItemsDTO>();
                        }
                        _ServiceItemsDTOs_Update.Add(t);
                    }
                });
                if (!_ServiceItemsDTOs_Insert.IsNullOrEmpty())
                {
                    await Db.InsertAsync(_ServiceItemsDTOs_Insert);
                }
                if (!_ServiceItemsDTOs_Update.IsNullOrEmpty())
                {
                    await Db.UpdateAsync(_ServiceItemsDTOs_Update);
                }
            }
        }

        /// <summary>
        /// 添加审批记录
        /// </summary>
        /// <param name="data"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        private async Task<bool> AddApprovalAsync(GBT_ServiceRequestDTO data, string userId)
        {
            List<GBT_ApprovalDTO> _ApprovalDTOs = await GetApprovalHistoryAsync(data.Id);
            var _Approval = _ApprovalDTOs.Where(t => t.CreatorId == userId && t.ServiceRequestId == data.Id).FirstOrDefault();
            //审批记录不存在时，新增审批记录
            if (_Approval.IsNullOrEmpty())
            {
                _Approval = new GBT_ApprovalDTO();
                string approver = null;
                switch (data.State)
                {
                    case 0:
                        //发起
                        approver = data.CreatorId;
                        break;
                    case 1:
                        //经理审批
                        approver = userId;
                        break;
                    case 2:
                        //完工确认
                        approver = data.DeliveryUsers.Where(t => t.UserId == userId).FirstOrDefault()?.UserId;
                        break;
                    case 3:
                        //评价
                        approver = data.RequestUsers.Where(t => t.UserId == userId).FirstOrDefault()?.UserId;
                        break;
                }
                if (!approver.IsNullOrEmpty())
                {
                    _Approval.Id = IdHelper.GetId();
                    _Approval.ServiceRequestId = data.Id;
                    _Approval.UserId = approver;
                    _Approval.DepartmentId = data.DeliveryDepartmentId;
                    _Approval.State = data.State;
                    _Approval.CreatorId = userId;
                    _Approval.CreateTime = DateTime.Now;
                    _Approval.Remark = data.ApprovalOpinion;
                    await Db.InsertAsync(_Approval);
                    return true;
                }
            }
            return false;
        }

        #endregion
    }
}